<script setup>
import { onMounted, ref, computed } from 'vue';
import useAssistantSettingStore from './AssistantStore';
import { llm_factories_list } from '@/api/assistant';
import { CODE } from '@/api/constants';
import { ElMessage } from 'element-plus';
import { getLlmIcon } from './utils';

// 获取可选模型列表参数
const factories_list = ref([])
const llms_list = computed(() => {
    const item = factories_list.value.find(item => item.name === assistantStore.modelForm.llm_factory)
    return item ? item.llm : []
})
const selectLogo = computed(() => {
    const item = factories_list.value.find(item => item.name === assistantStore.modelForm.llm_factory)
    return item.logo
})
onMounted(async() => {
    const resp = await llm_factories_list()
    if (resp.code != CODE.OK) {
        ElMessage({
            message: '获取支持的模型列表失败，请刷新后重试！',
            type: 'error',
            duration: 3000
        })
        return
    }
    factories_list.value = resp.data.factory_llm_infos
})

// 提交后端api表单数据
const assistantStore = useAssistantSettingStore()

// 控制ui功能
const isSelectFactory = computed(() => {
    return assistantStore.modelForm.llm_factory !== ""
})

// 自由度控制
const modelVariableType = Object.freeze({
  Improvise: 'Improvise',
  Balance: 'Balance',
  Precise: 'Precise',
})

const settledModelVariableMap = {
  [modelVariableType.Improvise]: {
    temperature: 0.9,
    top_p: 0.9,
    frequency_penalty: 0.2,
    presence_penalty: 0.4,
  },
  [modelVariableType.Balance]: {
    temperature: 0.5,
    top_p: 0.5,
    frequency_penalty: 0.7,
    presence_penalty: 0.4,
  },
  [modelVariableType.Precise]: {
    temperature: 0.1,
    top_p: 0.3,
    frequency_penalty: 0.7,
    presence_penalty: 0.4,
  },
};

const freedom = ref(modelVariableType.Balance)
const freeChoice2Str = {
    [modelVariableType.Improvise]: "即兴创作",
    [modelVariableType.Balance]: "平衡",
    [modelVariableType.Precise]: "精确",
}
function onFreedomChange(selectedVal) {
    for (const [key, value] of Object.entries(settledModelVariableMap[selectedVal])) {
        assistantStore.modelForm.llm_setting[key] = value
    }
}

const freeParam2Str = {
    temperature: "温度",
    top_p: "Top P",
    frequency_penalty: "存在处罚",
    presence_penalty: "频率惩罚",
}
</script>

<template>
    <div class="tab-container">
        <el-form :model="assistantStore.modelForm" label-width="auto">
            <el-form-item label="模型提供商" required>
                <el-select v-model="assistantStore.modelForm.llm_factory" placeholder="" no-data-text="暂无数据">
                    <template #prefix v-if="isSelectFactory">
                        <el-image :src="getLlmIcon(selectLogo)" fit="fill"
                            style="width: 20px; height: 20px;"></el-image>
                    </template>
                    <el-option v-for="f in factories_list"
                    :key="f.name"
                    :label="f.name"
                    :value="f.name">
                    <div style="display: flex; align-items: center">
                        <el-image :src="getLlmIcon(f.logo)" fit="fill"
                            style="width: 20px; height: 20px;"></el-image>
                        <span style="margin-left: 8px">{{ f.name }}</span>
                    </div>
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="API Key" required>
                <el-input v-model.trim="assistantStore.modelForm.api_key" :disabled="!isSelectFactory"></el-input>
            </el-form-item>
            <el-form-item label="模型" required>
                <el-select v-model="assistantStore.modelForm.llm" :disabled="!isSelectFactory" placeholder="" no-data-text="暂无数据" value-key="llm_name">
                    <el-option v-for="l in llms_list"
                    :key="l.llm_name"
                    :label="l.llm_name"
                    :value="l">
                    </el-option>
                </el-select>
            </el-form-item>
            <el-card shadow="never">
                <template #header style="margin: 2px;">
                    <div class="card-header">
                        <el-text size="large" tag="b">自由度</el-text>
                        <span class="spacer"></span>
                        <el-select v-model="freedom" size="large" style="max-width: 160px; font-size: large;" @change="onFreedomChange">
                            <el-option v-for="item in modelVariableType"
                                :key="item"
                                :label="freeChoice2Str[item]"
                                :value="item">
                            </el-option>
                        </el-select>
                    </div>
                </template>
                <div class="card-body">
                    <div v-for="(value, key) in freeParam2Str" class="freedom-param-line">
                        <el-space wrap size="default">
                            <el-text>{{ value }}</el-text>
                            <el-switch v-model="assistantStore.modelForm.fieldSwitches[key]" size="small" :disabled="!isSelectFactory"/>
                            <el-slider v-model="assistantStore.modelForm.llm_setting[key]" :disabled="!isSelectFactory || !assistantStore.modelForm.fieldSwitches[key]"
                                :min="0.0" :max="1.0" :step="0.01" show-input 
                                style="width: 350px;" size="small"/>
                        </el-space>
                    </div>
                </div>
            </el-card>
        </el-form>
    </div>
</template>

<style scoped>
.tab-container {
    width: 100%;
    height: 100%;
}

.card-header {
    display: flex;
    flex-direction: row;
}

.spacer {
    flex-grow: 1;
}

.tab-container :deep(.el-card__header) {
  background-color: rgb(226, 233, 247);
  padding: 10px 20px; /* 调整header内边距 */
}

.card-body {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

.freedom-param-line {
    display: inline-flex;
    flex-direction: row;
    justify-content: flex-end;
    padding: 6px 0px;
}

.factory-select-row {
    display: inline-flex;
    flex-direction: row;
}
</style>